package com.zyf.concurrency.chapter13;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 带有时间限制的加锁
 * 引自原文：
 *      在程序清单6-17 TimeBudget 的旅游门户网站示例中，为询价的每个汽车租赁公司都创建了一个独立的
 * 任务。询价操作包含某种基于网络的请求机制，例如Web服务请求。但在询价操作中同样可能
 * 需要实现对紧缺资源的独占访问，例如通向公司的直连通信线路。
 *      9.5节介绍了确保对资源进行串行访问的方法:一个单线程的Executor。另一种方法是使
 * 用一个独占锁来保护对资源的访问。程序清单13-4试图在Lock保护的共享通信线路.上发送一
 * 条消息，如果不能在指定时间内完成，代码就会失败。定时的tryLock能够在这种带有时间限
 * 制的操作中实现独占加锁行为。
 * create by yifeng
 */
public class TimedLocking {
    private Lock lock = new ReentrantLock();

    public boolean trySendOnSharedLine(String message,
                                       long timeout, TimeUnit unit)
           throws InterruptedException {
        // timeout-消息发送的时间 = 锁最终需要等待的时间
        // 不用担心nanosToLock为负数，在 {@code java.util.concurrent}
        long nanosToLock = unit.toNanos(timeout)
                - estimatedNanosToSend(message);
        if (!lock.tryLock(nanosToLock, TimeUnit.NANOSECONDS)) {
            return false;
        }
        try {
            return sendOnSharedLine(message);
        } finally {
            lock.unlock();
        }
    }

    private boolean sendOnSharedLine(String message) {
        // 发送一些什么
        return true;
    }
    // 返回发送消息的时间
    long estimatedNanosToSend(String message) {
        return message.length();
    }
}
